<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
    />
    <meta
      name="description"
      content="Fly to a specified location or view a geographic rectangle."
    />
    <meta name="cesium-sandcastle-labels" content="Showcases" />
    <title>Cesium Demo</title>
    <script type="text/javascript" src="../Sandcastle-header.js"></script>
    <script
      type="text/javascript"
      src="../../../Build/CesiumUnminified/Cesium.js"
      nomodule
    ></script>
    <script type="module" src="../load-cesium-es6.js"></script>
  </head>
  <body
    class="sandcastle-loading"
    data-sandcastle-bucket="bucket-requirejs.html"
  >
    <style>
      @import url(../templates/bucket.css);

      #viewChanged,
      #cameraChanged {
        display: none;
        background-color: red;
        color: white;
      }
    </style>
    <div id="cesiumContainer" class="fullSize"></div>
    <div id="loadingOverlay"><h1>Loading...</h1></div>
    <div id="toolbar">
      <div id="viewChanged">View Changed</div>
      <div id="cameraChanged">Camera Changed</div>
    </div>
    <script id="cesium_sandcastle_script">
      window.startup = async function (Cesium) {
        "use strict";
        //Sandcastle_Begin
        const viewer = new Cesium.Viewer("cesiumContainer");
        const scene = viewer.scene;
        const clock = viewer.clock;
        let referenceFramePrimitive;

        function flyToSanDiego() {
          Sandcastle.declare(flyToSanDiego);
          viewer.camera.flyTo({
            destination: Cesium.Cartesian3.fromDegrees(-117.16, 32.71, 15000.0),
          });
        }

        function flyToHeadingPitchRoll() {
          Sandcastle.declare(flyToHeadingPitchRoll);
          viewer.camera.flyTo({
            destination: Cesium.Cartesian3.fromDegrees(-122.22, 46.12, 5000.0),
            orientation: {
              heading: Cesium.Math.toRadians(20.0),
              pitch: Cesium.Math.toRadians(-35.0),
              roll: 0.0,
            },
          });
        }

        function flyToLocation() {
          Sandcastle.declare(flyToLocation);

          // Create callback for browser's geolocation
          function fly(position) {
            viewer.camera.flyTo({
              destination: Cesium.Cartesian3.fromDegrees(
                position.coords.longitude,
                position.coords.latitude,
                1000.0
              ),
            });
          }

          // Ask browser for location, and fly there.
          navigator.geolocation.getCurrentPosition(fly);
        }

        function viewRectangle() {
          Sandcastle.declare(viewRectangle);

          const west = -77.0;
          const south = 38.0;
          const east = -72.0;
          const north = 42.0;

          const rectangle = Cesium.Rectangle.fromDegrees(
            west,
            south,
            east,
            north
          );
          viewer.camera.setView({
            destination: rectangle,
          });

          // Show the rectangle.  Not required; just for show.
          viewer.entities.add({
            rectangle: {
              coordinates: rectangle,
              fill: false,
              outline: true,
              outlineColor: Cesium.Color.WHITE,
            },
          });
        }

        function flyToRectangle() {
          Sandcastle.declare(flyToRectangle);

          const west = -90.0;
          const south = 38.0;
          const east = -87.0;
          const north = 40.0;
          const rectangle = Cesium.Rectangle.fromDegrees(
            west,
            south,
            east,
            north
          );

          viewer.camera.flyTo({
            destination: rectangle,
          });

          // Show the rectangle.  Not required; just for show.
          viewer.entities.add({
            rectangle: {
              coordinates: rectangle,
              fill: false,
              outline: true,
              outlineColor: Cesium.Color.WHITE,
            },
          });
        }

        function setReferenceFrame() {
          Sandcastle.declare(setReferenceFrame);

          const center = Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883);
          const transform = Cesium.Transforms.eastNorthUpToFixedFrame(center);

          // View in east-north-up frame
          const camera = viewer.camera;
          camera.constrainedAxis = Cesium.Cartesian3.UNIT_Z;
          camera.lookAtTransform(
            transform,
            new Cesium.Cartesian3(-120000.0, -120000.0, 120000.0)
          );

          // Show reference frame.  Not required.
          referenceFramePrimitive = scene.primitives.add(
            new Cesium.DebugModelMatrixPrimitive({
              modelMatrix: transform,
              length: 100000.0,
            })
          );
        }

        function setHeadingPitchRoll() {
          Sandcastle.declare(setHeadingPitchRoll);

          const camera = viewer.camera;
          camera.setView({
            destination: Cesium.Cartesian3.fromDegrees(
              -75.5847,
              40.0397,
              1000.0
            ),
            orientation: {
              heading: -Cesium.Math.PI_OVER_TWO,
              pitch: -Cesium.Math.PI_OVER_FOUR,
              roll: 0.0,
            },
          });
        }

        function icrf(scene, time) {
          if (scene.mode !== Cesium.SceneMode.SCENE3D) {
            return;
          }

          const icrfToFixed = Cesium.Transforms.computeIcrfToFixedMatrix(time);
          if (Cesium.defined(icrfToFixed)) {
            const camera = viewer.camera;
            const offset = Cesium.Cartesian3.clone(camera.position);
            const transform = Cesium.Matrix4.fromRotationTranslation(
              icrfToFixed
            );
            camera.lookAtTransform(transform, offset);
          }
        }

        function viewInICRF() {
          Sandcastle.declare(viewInICRF);

          viewer.camera.flyHome(0);

          clock.multiplier = 3 * 60 * 60;
          scene.postUpdate.addEventListener(icrf);
          scene.globe.enableLighting = true;
        }

        const viewChanged = document.getElementById("viewChanged");

        let removeStart;
        let removeEnd;

        function cameraEvents() {
          Sandcastle.declare(cameraEvents);

          const camera = viewer.camera;
          removeStart = camera.moveStart.addEventListener(function () {
            viewChanged.style.display = "block";
          });
          removeEnd = camera.moveEnd.addEventListener(function () {
            viewChanged.style.display = "none";
          });
        }

        const cameraChanged = document.getElementById("cameraChanged");

        let removeChanged;

        function cameraChanges() {
          Sandcastle.declare(cameraChanges);

          let i = 0;
          removeChanged = viewer.camera.changed.addEventListener(function (
            percentage
          ) {
            ++i;
            cameraChanged.innerText = `Camera Changed: ${i}, ${percentage.toFixed(
              6
            )}`;
            cameraChanged.style.display = "block";
          });
        }

        function flyInACity() {
          Sandcastle.declare(flyInACity);

          const camera = scene.camera;
          camera.flyTo({
            destination: Cesium.Cartesian3.fromDegrees(
              -73.98580932617188,
              40.74843406689482,
              363.34038727246224
            ),
            complete: function () {
              setTimeout(function () {
                camera.flyTo({
                  destination: Cesium.Cartesian3.fromDegrees(
                    -73.98585975679403,
                    40.75759944127251,
                    186.50838555841779
                  ),
                  orientation: {
                    heading: Cesium.Math.toRadians(200.0),
                    pitch: Cesium.Math.toRadians(-50.0),
                  },
                  easingFunction: Cesium.EasingFunction.LINEAR_NONE,
                });
              }, 1000);
            },
          });
        }

        function losAngelesToTokyo(adjustPitch) {
          const camera = scene.camera;

          const tokyoOptions = {
            destination: Cesium.Cartesian3.fromDegrees(
              139.8148,
              35.7142,
              20000.0
            ),
            orientation: {
              heading: Cesium.Math.toRadians(15.0),
              pitch: Cesium.Math.toRadians(-60),
              roll: 0.0,
            },
            duration: 20,
            flyOverLongitude: Cesium.Math.toRadians(60.0),
          };

          const laOptions = {
            destination: Cesium.Cartesian3.fromDegrees(
              -117.729,
              34.457,
              10000.0
            ),
            duration: 5,
            orientation: {
              heading: Cesium.Math.toRadians(-15.0),
              pitch: -Cesium.Math.PI_OVER_FOUR,
              roll: 0.0,
            },
          };

          laOptions.complete = function () {
            setTimeout(function () {
              camera.flyTo(tokyoOptions);
            }, 1000);
          };

          if (adjustPitch) {
            tokyoOptions.pitchAdjustHeight = 1000;
            laOptions.pitchAdjustHeight = 1000;
          }

          camera.flyTo(laOptions);
        }

        function flyOverLongitude(adjustPitch) {
          Sandcastle.declare(flyOverLongitude);
          losAngelesToTokyo();
        }

        function flyOverLongitudeWithPitch() {
          Sandcastle.declare(flyOverLongitudeWithPitch);
          losAngelesToTokyo(true);
        }

        Sandcastle.addToolbarMenu([
          {
            text: "Camera Options",
          },
          {
            text: "Fly in a city",
            onselect: function () {
              reset();
              flyInACity();
              Sandcastle.highlight(flyInACity);
            },
          },
          {
            text: "Fly to San Diego",
            onselect: function () {
              reset();
              flyToSanDiego();
              Sandcastle.highlight(flyToSanDiego);
            },
          },
          {
            text: "Fly to Location with heading, pitch and roll",
            onselect: function () {
              reset();
              flyToHeadingPitchRoll();
              Sandcastle.highlight(flyToHeadingPitchRoll);
            },
          },
          {
            text: "Fly to My Location",
            onselect: function () {
              reset();
              flyToLocation();
              Sandcastle.highlight(flyToLocation);
            },
          },
          {
            text: "Fly to Rectangle",
            onselect: function () {
              reset();
              flyToRectangle();
              Sandcastle.highlight(flyToRectangle);
            },
          },
          {
            text: "View a Rectangle",
            onselect: function () {
              reset();
              viewRectangle();
              Sandcastle.highlight(viewRectangle);
            },
          },
          {
            text: "Set camera reference frame",
            onselect: function () {
              reset();
              setReferenceFrame();
              Sandcastle.highlight(setReferenceFrame);
            },
          },
          {
            text: "Set camera with heading, pitch, and roll",
            onselect: function () {
              reset();
              setHeadingPitchRoll();
              Sandcastle.highlight(setHeadingPitchRoll);
            },
          },
          {
            text: "View in ICRF",
            onselect: function () {
              reset();
              viewInICRF();
              Sandcastle.highlight(viewInICRF);
            },
          },
          {
            text: "Move events",
            onselect: function () {
              reset();
              cameraEvents();
              Sandcastle.highlight(cameraEvents);
            },
          },
          {
            text: "Camera changed event",
            onselect: function () {
              reset();
              cameraChanges();
              Sandcastle.highlight(cameraChanges);
            },
          },
          {
            text: "Fly from Los Angeles to Tokyo via Europe",
            onselect: function () {
              reset();
              flyOverLongitude();
              Sandcastle.highlight(flyOverLongitude);
            },
          },
          {
            text: "Look down during exaggerated flight",
            onselect: function () {
              reset();
              flyOverLongitudeWithPitch();
              Sandcastle.highlight(flyOverLongitudeWithPitch);
            },
          },
        ]);

        Sandcastle.addToolbarButton("Complete Flight", function () {
          scene.camera.completeFlight();
        });

        Sandcastle.addToolbarButton("Cancel Flight", function () {
          scene.camera.cancelFlight();
        });

        function reset() {
          scene.completeMorph();
          viewer.entities.removeAll();
          scene.primitives.remove(referenceFramePrimitive);
          scene.tweens.removeAll();

          if (Cesium.defined(removeStart)) {
            removeStart();
            removeEnd();

            viewChanged.style.display = "none";

            removeStart = undefined;
            removeEnd = undefined;
          }

          if (Cesium.defined(removeChanged)) {
            removeChanged();
            removeChanged = undefined;

            cameraChanged.style.display = "none";
          }

          viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);

          clock.multiplier = 1.0;
          scene.postUpdate.removeEventListener(icrf);
          scene.globe.enableLighting = false;
        }

        scene.morphComplete.addEventListener(function () {
          reset();
        });
        //Sandcastle_End
      };
      if (typeof Cesium !== "undefined") {
        window.startupCalled = true;
        window.startup(Cesium).catch((error) => {
          "use strict";
          console.error(error);
        });
        Sandcastle.finishedLoading();
      }
    </script>
  </body>
</html>
